/*
  initest.cc - test harness for / demonstration of IniFile.

  initest.ini should not exist prior to running and then should contain:

--- Begin expected initest.ini ---
Item 1 = One
Item 2 = Five

[ Section 1 ]
Item 1 = 2
Item 2 = 6

[ Section 2 ]
Item 1 = 3.5
Item 2 = 7.5

[ Section 4 ]
Item 1 = False
Item 3 = Off
--- End expected initest.ini ---

  When run again, initest.ini should become:

--- Begin expected 2nd initest.ini ---
Item 1 =
Item 2 = Five

[ Section 1 ]
Item 2 = 999,999

[ Section 2 ]
Item 1 = 3.5
Item 2 = 999.999

[ Section 4 ]
Item 1 = On
Item 3 = Off
--- End expected 2nd initest.ini ---

  (The first "Item 1" will have a space after the equal sign.)

  When run a third time, initest.ini should not change (ie. the timestamp
  should be the same as the second run).

  Other tests involve editing the file manually to add comments and duplicate
  sections and items.

*/

#include "inifile.h"

#define PassFail(test, result)\
if (!result) printf("%s failed.\n", test)

int main()
{
  IniFile ini;
  bool exists = ini.Open("initest.ini");

  // Test Open() function (if file exists).
  if (!exists)
  {
    puts("initest.ini does not exist - creating.");
  }

  // Test finding no item in an empty file, and no item in a section that has
  // items (the two default tests below).

  // Test explicit default values, "" for default section and overloaded
  // GetItem() functions.
  PassFail("Default GetItem (string)", strcmp(ini.GetItem("", "Item -1", "nothing"), "nothing") == 0);
  PassFail("Default GetItem (int)",    ini.GetItem("", "Item -2", -2)   == -2);
  PassFail("Default GetItem (double)", ini.GetItem("", "Item -3", -3.2) == -3.2);
  PassFail("Default GetItem (bool)",   ini.GetItem("", "Item -4", true) == true);

  // Test implicit default values and Get...() functions.
  PassFail("Default GetItem", *(ini.GetItem(  "Section 1", "Item -1")) == 0);
  PassFail("Default GetInt",    ini.GetInt(   "Section 1", "Item -2")  == 0);
  PassFail("Default GetDouble", ini.GetDouble("Section 1", "Item -2")  == 0.0);
  PassFail("Default GetBool",   ini.GetBool("Section 1", "Item -3")  == false);

  // Test file creation.
  if (!exists)
  {
    // Test overloaded WriteItem() functions and section and item creation.
    ini.WriteItem("",          "Item 1", "One");
    ini.WriteItem("Section 1", "Item 1", 2);
    ini.WriteItem("Section 2", "Item 1", 3.5);
    ini.WriteItem("Section 3", "Item 1", true);

    // Test the Write...() functions and item insertion.
    ini.WriteItem(  "",          "Item 2", "Five");
    ini.WriteInt(   "Section 1", "Item 2", 6);
    ini.WriteDouble("Section 2", "Item 2", 7.5);
    ini.WriteBool(  "Section 3", "Item 2", false);

    // Test the various boolean writes.
    ini.WriteTrueFalse("Section 4", "Item 1", false);
    ini.WriteYesNo(    "Section 4", "Item 2", true);
    ini.WriteOnOff(    "Section 4", "Item 3", false);
  }

  // Test the Write...() functions update items.
  else
  {
    ini.WriteItem( "",          "Item 1", "");
    ini.WriteItem( "Section 1", "Item 2", "999,999");
    ini.WriteItem( "Section 2", "Item 2", 999.999);
    ini.WriteOnOff("Section 4", "Item 1", true);
  }

  // Test the items were created/read successfully (and NULL for default
  // section).
  PassFail("Default section, Item 1", strcmp(ini.GetItem(NULL, "Item 1"), (exists) ? "" : "One") == 0);
  PassFail("Default section, Item 2", strcmp(ini.GetItem(NULL, "Item 2"), "Five") == 0);

  PassFail("Section 1, Item 1", ini.GetInt("Section 1", "Item 1") == 2);
  PassFail("Section 1, Item 2", ((exists) ? (strcmp(ini.GetItem("Section 1", "Item 2"), "999,999") == 0) : 6));

  PassFail("Section 2, Item 1", ini.GetDouble("Section 2", "Item 1") == 3.5);
  PassFail("Section 2, Item 2", ini.GetDouble("Section 2", "Item 2") == ((exists) ? 999.999 : 7.5));

  if (!exists)
  {
    PassFail("Section 3, Item 1", ini.GetBool("Section 3", "Item 1") == true);
    PassFail("Section 3, Item 2", ini.GetBool("Section 3", "Item 2") == false);
  }

  PassFail("Section 4, Item 1", ini.GetBool("Section 4", "Item 1") == (exists) ? true : false);
  if (!exists)
    PassFail("Section 4, Item 2", ini.GetBool("Section 4", "Item 2") == true);
  PassFail("Section 4, Item 3", ini.GetBool("Section 4", "Item 3") == false);

  const char** array;
  int num = ini.RetrieveSections(array);
  PassFail("RetrieveSections (count)", num == ((exists) ? 3 : 4));
  PassFail("RetrieveSections", strcmp(array[0], "Section 1") == 0);
  PassFail("RetrieveSections", strcmp(array[1], "Section 2") == 0);
  if (!exists)
  {
    PassFail("RetrieveSections", strcmp(array[2], "Section 3") == 0);
    PassFail("RetrieveSections", strcmp(array[3], "Section 4") == 0);
  }
  else
    PassFail("RetrieveSections", strcmp(array[2], "Section 4") == 0);
  delete[] array;

  num = ini.RetrieveItems("Section 4", array);
  PassFail("RetrieveItems (count)", num == ((exists) ? 2 : 3));
  PassFail("RetrieveItems", strcmp(array[0], "Item 1") == 0);
  if (!exists)
  {
    PassFail("RetrieveItems", strcmp(array[1], "Item 2") == 0);
    PassFail("RetrieveItems", strcmp(array[2], "Item 3") == 0);
  }
  else
    PassFail("RetrieveItems", strcmp(array[1], "Item 3") == 0);
  delete[] array;

  ini.RemoveSection("Section 3");
  ini.RemoveItem("Section 4", "Item 2");

  // Test the Close() function, via the destructor.
  return 0;
}
